/**
 ********************************************************************************
 *
 *文件名称：
 *
 *文件日期：
 *
 *文件描述：
 *
 *文件版本：
 *
 *修改历史：
 *
 ********************************************************************************
 ***/

/*******************************	头文件包含区	**********************************/
#include "sensor.h"
#include "icm40608.h"
/******************************* 全局变量定义区 **********************************/

#if (LED_STRUCTURE == NORMAL_STRUCTURE)
#if (PROJECT_TYPEDEF == CAT1)
#define KI ((float)1.0 / (float)18452.0)
#define KV ((float)220.0 / (float)3048438.0)
#define KP ((float)220.0 / (float)1702759.0)
#else
#define KI ((float)1.367 / (float)24384.0)
#define KV ((float)221.0 / (float)2977792.0)
#define KP ((float)297.0 / (float)2180608.0)
#endif
#else
#if (PROJECT_TYPEDEF == CAT1)
#define KI ((float)1.0 / (float)18452.0)
#define KV ((float)220.0 / (float)3048438.0)
#define KP ((float)220.0 / (float)1702759.0)
#else
#define KI ((float)0.5 / (float)9216.0)
#define KV ((float)220.0 / (float)3066399.0)
#define KP ((float)110.0 / (float)864519.0)
#endif
#endif
#define KI2 ((float)1.231 / (float)23808.0)
#define KP2	((float)248.7 / (float)2048000.0)


uint32_t alarm_send_data_flag = 0;
/**
 *********************************************************************************
 *
 *函数名称：
 *
 *函数参数：无
 *
 *函数返回值：无
 *
 *功能描述：
 *
 *********************************************************************************
 **/
void sensor_init(void)
{
	EMU->SPCMD = 0xe5; // 写使能位
					   //	EMU->HFConst 	= 	0x01B0;
					   //	EMU->IBGAIN 	= 	0x8906;
					   //	EMU->UGAIN 		= 	0x8561;
					   //	EMU->GPQA		= 	0x0000;

	EMU->HFConst = 1900;
	EMU->IAGAIN = 0;
	EMU->UGAIN = 0;
	EMU->GPQA = 0;
	EMU->SPCMD = 0xdc; // 写保护
}
/**
 *********************************************************************************
 *
 *函数名称：
 *
 *函数参数：无
 *
 *函数返回值：无
 *
 *功能描述：
 *
 *********************************************************************************
 **/

leakageDetection leakDete __attribute__((at(0x10000d50)));

#define LEAKAGE_DETEC_TIME 100 * 2
#define LEAKAGE_CYCLE 20

void intt_cycle_add(void)
{
	leakDete.intt_cycle++;
}

void leakage_Detection(void)
{
	if ((!leakDete.intt_cycle) && (!reg.R.alarm.LeakCurrent_bit))
		return;

	if (++leakDete.intt_time < LEAKAGE_DETEC_TIME)
		return;

	if (leakDete.intt_cycle >= LEAKAGE_CYCLE)
	{
		leakDete.intt_time = 0;
		leakDete.intt_cycle = 0;
		reg.R.alarm.LeakCurrent_bit = 1;
	}
	else
	{
		leakDete.intt_time = 0;
		leakDete.intt_cycle = 0;
		reg.R.alarm.LeakCurrent_bit = 0;
	}
}

void get_sensor(void)
{

	//static u32 energy2 = 0;

	bl0939_send();
	//check_max_power();	
	save_power_off_data();
	//告警
	if(reg.R.v == 0)
		return;
	alarm_check();
	
}
/**
 *********************************************************************************
 *
 *函数名称：
 *
 *函数参数：无
 *
 *函数返回值：无
 *
 *功能描述：
 *
 *********************************************************************************
 **/
int16_t get_temp(void)
{
	float temp_float;
	short temp, temp_int;
	char temp_c;
	temp = RTC->TEMP & 0x3ff;
	temp_float = (temp & 0x1) * 0.25 + ((temp >> 1) & 0x1) * 0.5;

	temp_c = (temp >> 2) & 0xff;
	if (temp_c & 0x80) //为负数
	{
		temp_int = 0xff00 | temp_c;
	}
	else
	{
		temp_int = temp_c;
	}
	temp_float = (temp_float + (float)temp_int) * 10;
	
	return (int16_t)temp_float;
}

void fnFront_ClockBatCalculate(void)
{
	u32 ClockBat;
	u8 i;

	for (i = 0; i < 255; i++)
	{
		if (!(MADC->AD_STAT & 0x02))
			break;
		__NOP();
		__NOP();
		__NOP();
		__NOP();
	}
	MADC->AD_CTRL = 0x0C;  // set ADCChannel 2  vbat  1倍增益
	MADC->AD_START = 0x01; // star ADC
	SystemDelay(1);
	for (i = 0; i < 150; i++)
	{
		if (MADC->AD_STAT & 0x01)
			break;
		__NOP();
		__NOP();
		__NOP();
		__NOP();
	}
	ClockBat = MADC->AD_DATA;
	// ClockBat = (ClockBat * 508)/1024;
	ClockBat = (ClockBat * 1) / 1024;
	//	Dl645Front.PubData.ClockBat = fnHexToBcd_u16((u16)(ClockBat));	//电池电压
	//当前温度值
	//	ClockBat = RTC->TEMP;
	//	ClockBat &= 0x3ff;
}
/**
 *********************************************************************************
 *
 *函数名称：
 *
 *函数参数：无
 *
 *函数返回值：无
 *
 *功能描述：
 *
 *********************************************************************************
 **/
last_alarm_bit last_alarm = {0};
last_alarm_bit alarm_last_value = {0};
const u16 *pAlarm = (u16 *)&reg.R.alarm;
const u16 *pLastAlarm = (u16 *)&last_alarm;

const alarm_struct alarmRegBuf[15][2] = {

	{{0x3004, 1}, {0x302A, 1}}, //温度告警及告警次数
	{{0x3006, 1}, {0x3029, 1}}, //电流1告警及告警次数
	{{0x3005, 1}, {0x3028, 1}}, //过压告警及告警次数
	{{0x3010, 2}, {0x3051, 1}}, //倾斜告警及告警次数
	{{0x302D, 1}, {0x3052, 1}}, //漏电告警及告警次数
	{{0x300B, 1}, {0x3029, 1}}, //电流2告警及告警次数
	{{0x1009, 1}, {0x3053, 1}}, //灯具1损坏告警及告警次数
	{{0x100A, 1}, {0x3054, 1}}, //灯具2损坏告警及告警次数
	{{0x3005, 1}, {0x3055, 1}}, //欠压告警及告警次数
	{{0x3007, 1}, {0x3056, 1}},	//过载告警及告警次数
	{{0x300C, 1}, {0x3056, 1}},	//第二路过载告警及告警次数
	{{0x1009, 1}, {0x3053, 1}}, //灯具1损坏告警及告警次数
	{{0x100A, 1}, {0x3054, 1}}, //灯具2损坏告警及告警次数
	{{0x3004, 1}, {0x305A, 1}}, //低温告警及告警次数
	{{0x1009, 1}, {0x3053, 1}}, //灯具1损坏告警及告警次数
};

void get_alarm_last_value(void)
{
	uint32_t timestampTable = TimeDate_To_TimeStamp(rtc_time.year, rtc_time.month, rtc_time.date, rtc_time.hour, rtc_time.min, rtc_time.sec);
	uint16_t lamp_offset;
	if(!((timestampTable > 1609430400) && (timestampTable < 4070880000)))
		timestampTable = 0;;
	timestampTable = swapUint32_t(timestampTable);

	if(alarm_last_value.Temp_bit != reg.R.alarm.Temp_bit && reg.R.alarm.Temp_bit)
	{
		ALARM_R.high_temp_alarm_max_last = reg.R.temp;
		ALARM_R.high_temp_alarm_max_last_time = timestampTable;
		data_flash_write(); //保存一次参数
	}
//	if(alarm_last_value.low_Temp_bit != reg.R.alarm.low_Temp_bit && reg.R.alarm.low_Temp_bit)
//	{
//		ALARM_R.low_temp_alarm_max_last = reg.R.temp;
//		ALARM_R.low_temp_alarm_max_last_time = timestampTable;
//		data_flash_write(); //保存一次参数
//	}
	if(alarm_last_value.I_bit != reg.R.alarm.I_bit && reg.R.alarm.I_bit)
	{
		ALARM_R.i_alarm_max_last = reg.R.i1;
		ALARM_R.i_alarm_max_last_time = timestampTable;
		data_flash_write(); //保存一次参数
	}
	if(alarm_last_value.U_bit != reg.R.alarm.U_bit && reg.R.alarm.U_bit)
	{
		ALARM_R.v_alarm_max_last = reg.R.v;
		ALARM_R.v_alarm_max_last_time = timestampTable;
		data_flash_write(); //保存一次参数
	}
	if(alarm_last_value.Titl_bit != reg.R.alarm.Titl_bit && reg.R.alarm.Titl_bit)
	{
		lamp_offset = (reg.R.lamp_xy_offset >> 8) > (reg.R.lamp_xy_offset & 0xFF)? reg.R.lamp_xy_offset >> 8 : (reg.R.lamp_xy_offset & 0xFF);
		lamp_offset = lamp_offset > (reg.R.lamp_z_offset >> 8)?  lamp_offset : (reg.R.lamp_z_offset >> 8);
		ALARM_R.titl_alarm_max_last = 0;
		ALARM_R.titl_alarm_max_last = lamp_offset;
		ALARM_R.titl_alarm_max_last_time = timestampTable;
		data_flash_write(); //保存一次参数
	}
	if(alarm_last_value.LeakCurrent_bit != reg.R.alarm.LeakCurrent_bit && reg.R.alarm.LeakCurrent_bit)
	{
		ALARM_R.lc_alarm_last_time = timestampTable;
		data_flash_write(); //保存一次参数
	}
	if(alarm_last_value.lowU_bit != reg.R.alarm.lowU_bit && reg.R.alarm.lowU_bit &&  (reg.R.v / 10 > reg.W.lowU_set/2))
	{
		ALARM_R.v_alarm_least_last = reg.R.v ;
		ALARM_R.v_alarm_least_last_time = timestampTable;
		data_flash_write(); //保存一次参数
	}
	if(alarm_last_value.power_bit != reg.R.alarm.power_bit && reg.R.alarm.power_bit )
	{
		ALARM_R.p_alarm_max_last = reg.R.p1 ;
		ALARM_R.p_u_alarm_max_last = reg.R.v ;
		ALARM_R.p_i_alarm_max_last = reg.R.i1 ;
		ALARM_R.p_alarm_max_last_time = timestampTable;
		data_flash_write(); //保存一次参数
	}
	alarm_last_value = reg.R.alarm;
}
void get_alarm_max_value(void)
{
	uint32_t timestampTable = TimeDate_To_TimeStamp(rtc_time.year, rtc_time.month, rtc_time.date, rtc_time.hour, rtc_time.min, rtc_time.sec);
	uint16_t lamp_offset;
	if(!((timestampTable > 1609430400) && (timestampTable < 4070880000)))
		timestampTable = 0;
		//return;
	timestampTable = swapUint32_t(timestampTable);
	if(reg.R.alarm.Temp_bit)
	{
		if(reg.R.temp > ALARM_R.high_temp_alarm_max + 10)
		{
			ALARM_R.high_temp_alarm_max = reg.R.temp;
			ALARM_R.high_temp_alarm_max_time = timestampTable;
			data_flash_write(); //保存一次参数
		} 
	}
//	if(reg.R.alarm.low_Temp_bit)
//	{
//		if(reg.R.temp < ALARM_R.low_temp_alarm_max - 10)
//		{
//			ALARM_R.low_temp_alarm_max = reg.R.temp;
//			ALARM_R.low_temp_alarm_max_time = timestampTable;
//			data_flash_write(); //保存一次参数
//		} 

//	}
	if(reg.R.alarm.U_bit)
	{
		if(reg.R.v > (ALARM_R.v_alarm_max * 1.01))
		{
			ALARM_R.v_alarm_max = reg.R.v;
			ALARM_R.v_alarm_max_time = timestampTable;
			data_flash_write(); //保存一次参数
		}
	}
	if(reg.R.alarm.I_bit)
	{
		if(reg.R.i1 > ALARM_R.i_alarm_max* 1.01 ) 
		{
			ALARM_R.i_alarm_max = reg.R.i1;
			ALARM_R.i_alarm_max_time = timestampTable;
			data_flash_write(); //保存一次参数
		}
	}
	if(reg.R.alarm.lowU_bit)
	{
		if(reg.R.v < ALARM_R.v_alarm_least * 0.99  &&  (reg.R.v / 10 > reg.W.lowU_set/2))
		{
			ALARM_R.v_alarm_least = reg.R.v ;
			ALARM_R.v_alarm_least_time = timestampTable;
			data_flash_write(); //保存一次参数
		}
	}
	if(reg.R.alarm.Titl_bit)
	{
		lamp_offset = (reg.R.lamp_xy_offset >> 8) > (reg.R.lamp_xy_offset & 0xFF)? reg.R.lamp_xy_offset >> 8 : (reg.R.lamp_xy_offset & 0xFF);
		lamp_offset = lamp_offset > (reg.R.lamp_z_offset >> 8)?  lamp_offset : (reg.R.lamp_z_offset >> 8);
		
		if(lamp_offset > ALARM_R.titl_alarm_max)
		{
			ALARM_R.titl_alarm_max = lamp_offset;
			ALARM_R.titl_alarm_max_time = timestampTable;
			data_flash_write(); //保存一次参数
		}
	}

	if(reg.R.alarm.power_bit)
	{
		if(reg.R.p1 > ALARM_R.p_alarm_max)
		{
			ALARM_R.p_alarm_max = reg.R.p1 ;
			ALARM_R.p_u_alarm_max = reg.R.v ;
			ALARM_R.p_i_alarm_max = reg.R.i1 ;
			ALARM_R.p_alarm_max_time = timestampTable;
			data_flash_write(); //保存一次参数
		}
	}
}

//uint16_t lowU_time = 0;
void alarm_check(void)
{
	static u8 alarm_time = 0;
  
  static uint16_t get_alarm_max_pLast_value = 0;
	static uint16_t lowU_time = 0;
	static u8 get_alarm_max_value_time = 0;

	static u8 get_alarm_last_value_time = 0;
	uint16_t Lamp_damage_power = 0;
	uint8_t mini_brightness = 0;
	static u8 compensate_power = 1;
	
	if(reg.R.v < 800)
		if(++lowU_time <8000)
			return;
	
	reg.R.alarm.Temp_bit = (reg.R.temp > reg.W.temp_alarm_set) ? 1 : (reg.R.temp < (reg.W.temp_alarm_set - 5)) ? 0
																											   : reg.R.alarm.Temp_bit;
//	reg.R.alarm.low_Temp_bit = (reg.R.temp < reg.W.low_temp_alarm_set) ? 1 : (reg.R.temp > (reg.W.low_temp_alarm_set + 5)) ? 0
//																											   : reg.R.alarm.Temp_bit;

	reg.R.alarm.I_bit = (reg.R.i1 > reg.W.i_alarm_set) ? 1 : (reg.R.i1 < (reg.W.i_alarm_set - 5)) ? 0
																								  : reg.R.alarm.I_bit;
	reg.R.alarm.U_bit = (reg.R.v / 10 > reg.W.v_alarm_set) ? 1 : ((reg.R.v / 10) < (reg.W.v_alarm_set - 5)) ? 0
																											: reg.R.alarm.U_bit;
//	reg.R.alarm.LeakCurrent_bit = (reg.R.i1 > reg.W.i_alarm_set) ? 1 : (reg.R.i1 < (reg.W.i_alarm_set - 5)) ? 0
//																								  : reg.R.alarm.I_bit;
	reg.R.alarm.I2_bit = 0;//(reg.R.i2 > reg.W.i_alarm_set) ? 1 : 0;
	//reg.R.alarm.Lamp1_bit = (reg.RW.lamp[0].sw == 1 && reg.R.i1 < 30) ? 1 : 0;
	
	//reg.R.alarm.Lamp1_bit = (reg.RW.lamp[0].sw == 1 && reg.R.p1 < 12) ? 1 : 0;

	reg.R.alarm.Lamp2_bit = 0;//(reg.RW.lamp[1].sw == 1 && reg.R.i2 < 30) ? 1 : 0;
	reg.R.alarm.Lamp2_bit = 0;
	
	if(reg.R.v > 300 && (reg.R.v / 10 < reg.W.lowU_set))
	{
		if(++lowU_time > 3000)
		{
			reg.R.alarm.lowU_bit = 1;
			lowU_time = 0;
		}
	}
	else
	{
			reg.R.alarm.lowU_bit = 0;
			lowU_time = 0;
	}
		//reg.R.alarm.lowU_bit = (reg.R.v / 10 < reg.W.lowU_set) ? (reg.R.v / 10 < reg.W.lowU_set/2)? reg.R.alarm.lowU_bit : 1 : 0;
	reg.R.alarm.power_bit = (reg.R.p1 > reg.W.power_set) ? 1 : (reg.R.p1 < (reg.W.power_set - 10)) ? 0
																								   : reg.R.alarm.power_bit;
	reg.R.alarm.power_bit2 = 0;//(reg.R.p2 > reg.W.power_set) ? 1 : (reg.R.p2 < (reg.W.power_set - 10)) ? 0
								//																	: reg.R.alarm.power_bit2;
	reg.R.alarm.lamp2Dimming_bit = 0;
	reg.R.alarm.Lamp2_failure = 0;

	if(!reg.W.detection_dimming)
	{
		reg.R.alarm.Lamp1_bit = 0;
		reg.R.alarm.Lamp_failure = 0;
	}
	else if((reg.RW.lamp[0].sw & 0x01)== 1)
	{
		if(power.ten_percent_power >  5)
		{
			Lamp_damage_power = power.ten_percent_power - 5;
			mini_brightness = 10;
		}	
		else
		{
			Lamp_damage_power = LEAST_POWER;
			mini_brightness = 30;
		}
			
		if(reg.RW.lamp[0].light >= mini_brightness)	
		{
			if(reg.R.p1 < Lamp_damage_power)
			{
				if(reg.R.p1 == 0)
				{
					reg.R.alarm.Lamp1_bit = 1;   //功率為0，電源損壞
					reg.R.alarm.Lamp_failure = 0;
					compensate_power = 3;
				}
				else if(reg.R.p1 > compensate_power)
				{
					reg.R.alarm.Lamp1_bit = 0; 
					reg.R.alarm.Lamp_failure = 1;  //功率不為0，灯具損壞
				}
			}
			else
			{
				reg.R.alarm.Lamp1_bit = 0;
				reg.R.alarm.Lamp_failure = 0;
			}
		}

	}
	else if((reg.RW.lamp[0].sw & 0x01)== 0)
	{
		reg.R.alarm.Lamp1_bit = 0;
		reg.R.alarm.Lamp_failure = 0;
		reg.R.alarm.lamp1Dimming_bit = 0;
	}


	if(get_alarm_max_pLast_value != *pAlarm)
	{
		get_alarm_last_value_time ++;
		if(get_alarm_last_value_time >= 200)
		{
			get_alarm_max_pLast_value = *pAlarm;
			get_alarm_last_value_time= 0;
			get_alarm_last_value();
			get_alarm_max_value();
		}
	}
	else
	{
		get_alarm_max_value_time ++;
		if(get_alarm_max_value_time >= 100)
		{
			get_alarm_max_value_time = 0;
			get_alarm_max_value();
		}
		get_alarm_last_value_time = 0;
		
	}

#if (PROJECT_TYPEDEF == NB)
	if (NB_LWM2M_OK != device_info.mqtt_state)
		return;
#elif (PROJECT_TYPEDEF == NB_ONENET)
	if (NB_LWM2M_OK != device_info.mqtt_state)
		return;
#elif (PROJECT_TYPEDEF == CAT1)
	if (!device_info.mqtt_state)
		return;
#endif

	global_control.alarm_flag = *pAlarm;
	if (*pAlarm != *pLastAlarm)
	{
		if ((++alarm_time) >= 200) // 2s
		{
			alarm_time = 0;
			
			if(last_alarm.Temp_bit != reg.R.alarm.Temp_bit && reg.R.alarm.Temp_bit)
			{
				reg.R.temp_alarm_count++;
			}
//			if(last_alarm.low_Temp_bit != reg.R.alarm.low_Temp_bit && reg.R.alarm.low_Temp_bit)
//			{
//				reg.R.low_temp_alarm_count++;
//			}
			if(last_alarm.I_bit != reg.R.alarm.I_bit && reg.R.alarm.I_bit)
			{
				reg.R.i_alarm_count++;
			}
			if(last_alarm.U_bit != reg.R.alarm.U_bit && reg.R.alarm.U_bit)
			{
				reg.R.v_alarm_count++;
			}
			if(last_alarm.Titl_bit != reg.R.alarm.Titl_bit && reg.R.alarm.Titl_bit)
			{
				reg.R.titl_alarm_cnt++;
			}
			if(last_alarm.LeakCurrent_bit != reg.R.alarm.LeakCurrent_bit && reg.R.alarm.LeakCurrent_bit)
			{
				reg.R.lc_alarm_cnt++;
			}
			if(last_alarm.Lamp1_bit != reg.R.alarm.Lamp1_bit && reg.R.alarm.Lamp1_bit)
			{
				reg.R.lamp1_alarm_cnt++;
			}
			if(last_alarm.lowU_bit != reg.R.alarm.lowU_bit && reg.R.alarm.lowU_bit)
			{
				reg.R.lowU_alarm_cnt++;
			}
			if(last_alarm.power_bit != reg.R.alarm.power_bit && reg.R.alarm.power_bit)
			{
				reg.R.power_alarm_cnt++;
			}

			if (reg.R.alarm.power_bit || reg.R.alarm.power_bit2 || reg.R.alarm.I_bit || reg.R.alarm.I2_bit || reg.R.alarm.U_bit) //过载或过流或过压时关闭继电器
			{
				//reg.RW.lamp[0].sw = 0;
#if (PROJECT_TYPEDEF == NB_ONENET || PROJECT_TYPEDEF == NB)
				//device_time.lamp_data_report_time = 120000 + device_info.random;
				device_time.lamp_data_report_time = reg.W.heartbeat_interval * 100 + device_info.random;
#else
				device_time.lamp_data_report_time = 60000 + device_info.random;
#endif
			}
			reportAlarmData(pAlarm, pLastAlarm);
			last_alarm = reg.R.alarm;
			lowU_time = 0;
		}
	}
	else
	{
		alarm_time = 0;
	}
}
/**
 * @description: 告警数据上报
 * @param {*}
 * @return {*}
 */

void reportAlarmData(const uint16_t *alarm, const uint16_t *lastAlarm)
{
	//LOGD("\r\n-----------------------------------------------------------------------------------------\r\n");
	if (reg.RW.ota_flag == OTA_READY)
		return;
	for (u8 i = 0; i < 15; i++)
	{
		if ((*alarm & (1 << i)) != (*lastAlarm & (1 << i)))
		{
			protocol.reg_num = 4;
			protocol.reg_addr[0] = 0x3001;
			protocol.reg_len[0] = 1;
			protocol.reg_addr[1] = alarmRegBuf[i][0].reg_addr;
			protocol.reg_len[1] = alarmRegBuf[i][0].len;
			protocol.reg_addr[2] = alarmRegBuf[i][1].reg_addr;
			protocol.reg_len[2] = alarmRegBuf[i][1].len;
			protocol.reg_addr[3] = 0x1003;
			protocol.reg_len[3] = 3;
#if (PROJECT_TYPEDEF == CAT1)
			my_cmd_deal(AT_QMTPUB_UPLINK, AT_TX_UPLINK10, AT_RX_UPLINK, 1, 1000, ACK);
			LOGD("test01:AT_TX_UPLINK10\r\n");
#endif
			my_cmd_deal(AT_QMTPUB_UP_LAMP, AT_TX_QMTPUB_UP_LAMP, waiting_to_receive, 1, 2000, ACK);
			alarm_send_data_flag = 1;
		}
	}
}




